import { FlowExportObject } from '@vue-flow/core'

// 定义节点和边的类型
interface Node {
  id: string
  // 其他字段...
}

interface Edge {
  source: string // 起点节点 ID
  target: string // 终点节点 ID
}

/**
 * 按流程顺序生成节点数组
 * @param nodes 所有节点
 * @param edges 所有边
 * @returns 按连接顺序排列的节点数组
 */
function getOrderedNodes(nodes: Node[], edges: Edge[]): Node[] {
  // 构建邻接表：记录每个节点的出边
  const adjacencyList = new Map<string, string[]>()
  // 记录每个节点的入度
  const inDegreeMap = new Map<string, number>()

  // 初始化邻接表和入度表
  nodes.forEach((node) => {
    adjacencyList.set(node.id, [])
    inDegreeMap.set(node.id, 0)
  })

  // 填充邻接表和入度表
  edges.forEach((edge) => {
    adjacencyList.get(edge.source)?.push(edge.target)
    inDegreeMap.set(edge.target, (inDegreeMap.get(edge.target) || 0) + 1)
  })

  // 拓扑排序队列
  const queue: string[] = []
  const orderedNodes: Node[] = []

  // 将入度为 0 的节点加入队列
  for (const [id, inDegree] of inDegreeMap.entries()) {
    if (inDegree === 0) {
      queue.push(id)
    }
  }

  // 执行拓扑排序
  while (queue.length > 0) {
    const currentId = queue.shift()!
    const currentNode = nodes.find((node) => node.id === currentId)

    if (currentNode) {
      orderedNodes.push(currentNode)
    }

    // 遍历当前节点的出边
    const neighbors = adjacencyList.get(currentId) || []
    for (const neighborId of neighbors) {
      // 更新邻居节点的入度
      const newInDegree = (inDegreeMap.get(neighborId) || 0) - 1
      inDegreeMap.set(neighborId, newInDegree)

      // 如果邻居节点入度为 0，加入队列
      if (newInDegree === 0) {
        queue.push(neighborId)
      }
    }
  }

  // 检查是否有循环依赖（如果 orderedNodes 的长度不等于 nodes，说明有环）
  if (orderedNodes.length !== nodes.length) {
    console.warn('流程图中存在循环依赖，无法生成完整顺序')
  }

  return orderedNodes
}

export function orderExportFlow(flowObj: FlowExportObject) {
  const { nodes, edges } = flowObj
  // 获取按流程顺序排列的节点
  const orderedNodes = getOrderedNodes(nodes, edges)

  return orderedNodes
}
